package org.pupil.socket.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.pupil.config.Properties;
import org.pupil.socket.codec.RpcDecoder;
import org.pupil.socket.codec.RpcEncoder;
import org.pupil.utils.IpUtil;

import java.net.InetSocketAddress;


/**
 * @Description: 服务提供方1
 * @Author: pupil
 * @Date: 2024/07/09 下午 4:31
 */
public class Server {

    private Integer port; // 监听端口

    private ServerBootstrap serverBootstrap;

    public Server(Integer port) {
        this.port = port;
    }

    // 启动服务提供方
    public void run() throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new RpcEncoder());
                            socketChannel.pipeline().addLast(new RpcDecoder());
                            socketChannel.pipeline().addLast(new ServerHandler());
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            if (port == null){
                // 随机绑定一个端口
                serverBootstrap.bind(0).addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture channelFuture) throws Exception {
                        // 绑定成功后的处理
                        if (channelFuture.isSuccess()) {
                            Channel channel = channelFuture.channel();
                            InetSocketAddress localAddress = (InetSocketAddress) channel.localAddress();
                            Properties.setPort(localAddress.getPort());
                        }
                    }
                }).sync().channel().closeFuture().sync();
            } else {
                serverBootstrap.bind(port).sync().channel().closeFuture().sync();
            }
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
